import * as THREE from 'three';
import { Tween, Easing, Interpolation } from '@tweenjs/tween.js';
import BasicScene, { BasicSceneOptions } from './BasicScene';
import RoundTween from '@/three/utils/RoundTween';

interface Default3DAxis {
  x: number;
  y: number;
  z: number;
}

/**
 * 0\~2 is angle, 3\~5 is position
 */
type CameraInfo = {
  position: Default3DAxis;
  rotation: Default3DAxis;
};

export interface CenterLogoSceneOptions extends BasicSceneOptions {
  CameraPosition: Record<string, CameraInfo>;
  camera: THREE.Camera;
  scene: THREE.Scene;
  renderer: THREE.WebGLRenderer;
}

export default class CenterLogoScene extends BasicScene {
  CameraPosition: Record<string, CameraInfo>;
  tweenR: Tween<Default3DAxis>;
  tweenP: Tween<Default3DAxis>;
  renderer: THREE.WebGLRenderer;

  constructor({ id, CameraPosition, camera, scene, ItemList, renderer, canvas }: CenterLogoSceneOptions) {
    super({ id, camera, scene, ItemList, canvas });
    this.CameraPosition = CameraPosition;
    this.tweenR = new Tween({
      x: 0,
      y: 0,
      z: 0,
    });
    this.tweenP = new Tween({
      x: 0,
      y: 0,
      z: 0,
    });
    this.renderer = renderer;
  }

  ChangeCameraPosition(pos: keyof typeof this.CameraPosition, duration = 2000, cb?: Function) {
    const fromR = {
      x: this.camera.rotation.x,
      y: this.camera.rotation.y,
      z: this.camera.rotation.z,
    };

    this.tweenR = new Tween(fromR)
      .interpolation(Interpolation.Bezier)
      .easing(Easing.Quadratic.InOut)
      .onUpdate(({ x, y, z }) => {
        this.camera.rotation.set(x, y, z);
      })
      .to(RoundTween(fromR, this.CameraPosition[pos].rotation), duration)
      .start();

    const fromP = {
      x: this.camera.position.x,
      y: this.camera.position.y,
      z: this.camera.position.z,
    };
    this.tweenP = new Tween(fromP)
      .interpolation(Interpolation.Bezier)
      .easing(Easing.Quadratic.InOut)
      .onUpdate(({ x, y, z }) => {
        this.camera.position.set(x, y, z);
      })
      .onComplete(() => {
        cb && cb();
      })
      .to(this.CameraPosition[pos].position, duration)
      .start();
  }

  StopTween() {
    this.tweenR.stop();
    this.tweenP.stop();
  }

  onSceneChange(id: string) {
    if (id != this.id) {
      this.StopTween();
      this.onCurrentSceneLeave && this.onCurrentSceneLeave();
      return;
    } else {
      this.onCurrentSceneEnter && this.onCurrentSceneEnter();
    }
  }

  animate() {
    this.tweenR.update();
    this.tweenP.update();
  }
}
